package com.lincoln.framework.utils;

import com.lincoln.framework.common.WebUtils;
import com.lincoln.framework.utils.FileUtilsEx;
import com.lincoln.framework.utils.JpegReader;
import com.lincoln.framework.utils.StringUtilsEx;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.commons.io.FileUtils;
import org.summercool.image.AnimatedGifEncoder;
import org.summercool.image.GifDecoder;
import org.summercool.image.Scalr;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.*;

/**
 * 图片处理工具类
 * 
 * @author zwm
 */
public class ImageUtils {

	/**
	 * 图片缩略处理的最大图片大小
	 */
	public static final long MAX_IMAGE_SIZE = 100 * 1024;

	public static final String TYPE_JPEG = "jpg";

	public static final String TYPE_PNG = "png";

	public static final String TYPE_GIF = "gif";

	public static final String TYPE_BMP = "bmp";

	/**
	 * 不更改图片质量，缩略图片
	 * 
	 * @param srcFilePath
	 *            图片所在的文件夹路径
	 * @param descFilePath
	 *            图片路径
	 * @param newWidth
	 *            目标宽
	 * @throws Exception
	 */
	public static void smallPictureWithWidth(String srcFilePath, String descFilePath, int newWidth) throws Exception {
		getSmallPicture(srcFilePath, descFilePath, newWidth, 0, 1);
	}

	/**
	 * 缩略图片
	 * 
	 * @param srcFilePath
	 *            图片所在的文件夹路径
	 * @param descFilePath
	 *            图片路径
	 * @param newWidth
	 *            目标宽
	 * @param newHeight
	 *            目标高
	 * @param per
	 *            （0.0 ～ 1.0） 图片质量百分比
	 * @throws Exception
	 */
	public static void getSmallPicture(String srcFilePath, String descFilePath, int newWidth, int newHeight, float per)
			throws Exception {
		getSmallPicture(srcFilePath, descFilePath, newWidth, newHeight, per, MAX_IMAGE_SIZE);
	}

	/**
	 * 缩略图片
	 * 
	 * @param srcFilePath
	 *            图片所在的文件夹路径
	 * @param descFilePath
	 *            图片路径
	 * @param newWidth
	 *            目标宽
	 * @param newHeight
	 *            目标高
	 * @param per
	 *            （0.0 ～ 1.0） 图片质量百分比
	 * @param maxSize
	 *            最大图片大小
	 * @throws Exception
	 */
	public static void getSmallPicture(String srcFilePath, String descFilePath, int newWidth, int newHeight, float per,
			long maxSize) throws Exception {
		BufferedImage src;
		try {
			File file = new File(srcFilePath);
			if (!file.exists() || !file.isFile()) {
				throw new Exception("转换源图片不存在！");
			}

			if (newWidth == 0 && newHeight == 0) {
				throw new Exception("设置高度、宽度均为0！");
			}
			src = ImageUtils.getBufferedImage(file);

			int oldWidth = src.getWidth(null);
			int oldHeight = src.getHeight(null);
			if (file.length() <= maxSize && oldWidth < newWidth) {
				FileUtils.copyFile(new File(srcFilePath), new File(descFilePath));
				return;
			}

			int tempNewHeight = (int) (newWidth * (oldHeight * 1.00 / oldWidth));
			if ((newHeight != 0 && tempNewHeight > newHeight) || tempNewHeight == 0) {
				newWidth = (int) (newHeight * (oldWidth * 1.00 / oldHeight));
			} else {
				newHeight = tempNewHeight;
			}
			redraw(new File(srcFilePath), new File(descFilePath), newWidth, newHeight, per);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw ex;
		}
	}

	/**
	 * 图片灰色处理
	 * 
	 * @throws IOException
	 */
	public static BufferedImage grayFilter(BufferedImage image) throws IOException {
		BufferedImage destImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
		ColorConvertOp cco = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
		cco.filter(image, destImage);
		return destImage;
	}

	/**
	 * 图片缩放
	 */
	public static void resize(File srcFile, File destFile, int maxWidth, int maxHeight, String type, float quality)
			throws Exception {
		if (TYPE_GIF.equals(type)) {
			resizeGif(srcFile, destFile, maxWidth, maxHeight);
		} else if (TYPE_PNG.equals(type)) {
			resizePng(srcFile, destFile, maxWidth, maxHeight);
		} else {
			resizeJpeg(srcFile, destFile, maxWidth, maxHeight, quality);
		}
	}

	/**
	 * 图片缩放
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param maxWidth
	 * @param maxHeight
	 * @param type
	 * @throws IOException
	 */
	public static void resize(File srcFile, File destFile, int maxWidth, int maxHeight, String type) throws Exception {
		resize(srcFile, destFile, maxWidth, maxHeight, type, 0.8f);
	}

	/**
	 * 图片缩放
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param maxWidth
	 * @param maxHeight
	 * @throws Exception
	 */
	public static void resize(File srcFile, File destFile, int maxWidth, int maxHeight, float quality) throws Exception {
		resize(srcFile, destFile, maxWidth, maxHeight, getType(srcFile), quality);
	}

	/**
	 * 图片缩放
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param maxWidth
	 * @param maxHeight
	 * @throws Exception
	 */
	public static void resize(File srcFile, File destFile, int maxWidth, int maxHeight) throws Exception {
		resize(srcFile, destFile, maxWidth, maxHeight, getType(srcFile));
	}

	/**
	 * JPEG图片缩放
	 */
	public static void resizeJpeg(File srcFile, File destFile, int width, int height, float quality) throws Exception {
		BufferedImage image = getBufferedImage(srcFile);

		double rate = getResizeRate(srcFile, width, height);
		width = (int) (image.getWidth() * rate);
		height = (int) (image.getHeight() * rate);

		image = Scalr.resize(image, Scalr.Method.AUTOMATIC, Scalr.Mode.AUTOMATIC, width, height);
		BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
		Graphics2D g = bufferedImage.createGraphics();
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
		g.fillRect(0, 0, image.getWidth(), image.getHeight());
		g.drawImage(image, 0, 0, null);
		g.dispose();
		image = bufferedImage;

		writeJpegFileSupportQuality(destFile, bufferedImage, quality);
	}

	/**
	 * PNG图片缩放
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param maxWidth
	 * @param maxHeight
	 * @throws IOException
	 */
	public static void resizePng(File srcFile, File destFile, int maxWidth, int maxHeight) throws Exception {
		BufferedImage bufferedImage = ImageIO.read(srcFile);
		double rate = getResizeRate(srcFile, maxWidth, maxHeight);
		if (rate == 1) {
			FileUtils.copyFile(srcFile, destFile);
		} else {
			int width = (int) (bufferedImage.getWidth() * rate);
			int height = (int) (bufferedImage.getHeight() * rate);
			BufferedImage result = Scalr.resize(bufferedImage, Scalr.Method.AUTOMATIC, Scalr.Mode.AUTOMATIC, width, height);
			ImageIO.write(result, "png", destFile);
		}
	}

	/**
	 * GIF图片缩放
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param maxWidth
	 * @param maxHeight
	 * @throws IOException
	 */
	public static void resizeGif(File srcFile, File destFile, int maxWidth, int maxHeight) throws Exception {
		GifDecoder gd = new GifDecoder();
		int status = gd.read(new FileInputStream(srcFile));
		if (status != GifDecoder.STATUS_OK) {
			return;
		}
		double rate = getResizeRate(srcFile, maxWidth, maxHeight);
		if (rate == 1) {
			FileUtils.copyFile(srcFile, destFile);
		} else {
			AnimatedGifEncoder ge = new AnimatedGifEncoder();
			ge.start(new FileOutputStream(destFile));
			ge.setRepeat(0);
			for (int i = 0; i < gd.getFrameCount(); i++) {
				BufferedImage frame = gd.getFrame(i);
				int width = frame.getWidth();
				int height = frame.getHeight();
				width = (int) (width * rate);
				height = (int) (height * rate);

				BufferedImage rescaled = Scalr.resize(frame, Scalr.Mode.FIT_EXACT, width, height);
				int delay = gd.getDelay(i);
				ge.setDelay(delay);
				ge.addFrame(rescaled);
			}
			ge.finish();
		}
	}

	/**
	 * 获取缩放比例
	 * 
	 * @param srcFile
	 * @param maxWidth
	 * @param maxHeight
	 * @return
	 * @throws IOException
	 */
	public static double getResizeRate(File srcFile, int maxWidth, int maxHeight) throws Exception {
		double rate = 1;
		if (maxWidth == 0 && maxHeight == 0) {
			return rate;
		}
		BufferedImage bImage = ImageUtils.getBufferedImage(srcFile);
		int width = bImage.getWidth();
		int height = bImage.getHeight();
		if (maxWidth == 0 && height > maxHeight) {
			rate = (double) maxHeight / height;
		} else if (maxHeight == 0 && width > maxWidth) {
			rate = (double) maxWidth / width;
		} else if ((width > maxWidth || height > maxHeight) && maxWidth > 0 && maxHeight > 0) {
			rate = (double) maxWidth / width > (double) maxHeight / height ? (double) maxHeight / height
					: (double) maxWidth / width;
		}
		if (rate > 1) {
			rate = 1;
		}
		return rate;
	}

	/**
	 * 获取图片类型（后缀）
	 * 
	 * @param file
	 * @return
	 */
	public static String getType(File file) throws Exception {
		String mimeType = FileUtilsEx.getMimeType(file);
		return getType(mimeType);
	}

	/**
	 * 获取图片类型（后缀）
	 * 
	 * @param mimeType
	 * @return
	 */
	public static String getType(String mimeType) {
		if ("image/gif".equals(mimeType)) {
			return TYPE_GIF;
		} else if ("image/png".equals(mimeType) || "image/x-png".equals(mimeType)) {
			return TYPE_PNG;
		} else if ("image/bmp".equals(mimeType) || "image/x-ms-bmp".equals(mimeType)) {
			return TYPE_BMP;
		}
		return TYPE_JPEG;
	}

	/**
	 * 图片重绘
	 */
	public static void redraw(File srcFile, File destFile, int width, int height, float quality) throws Exception {
		String type = getType(srcFile);
		if (TYPE_PNG.equals(type)) {
			redrawPng(srcFile, destFile, width, height);
		} else if (TYPE_GIF.equals(type)) {
			redrawGif(srcFile, destFile, width, height);
		} else {
			redrawJpegBmp(srcFile, destFile, width, height, quality);
		}
	}

	public static void redraw(File srcFile, File destFile, int width, int height) throws Exception {
		redraw(srcFile, destFile, width, height, 1.0f);
	}

	/**
	 * 重绘png
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param width
	 * @param height
	 * @throws Exception
	 */
	public static void redrawPng(File srcFile, File destFile, int width, int height) throws Exception {
		BufferedImage srcImage = ImageIO.read(srcFile);
		BufferedImage image;
		image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D gs = image.createGraphics();
		gs.drawImage(srcImage, 0, 0, width, height, null);
		gs.dispose();
		ImageIO.write(image, "png", destFile);
	}

	/**
	 * 重绘jpg/bmp格式
	 */
	public static void redrawJpegBmp(File srcFile, File destFile, int width, int height, float quality)
			throws Exception {
		BufferedImage image = getBufferedImage(srcFile);

		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = bufferedImage.createGraphics();
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
		g.fillRect(0, 0, width, height);
		g.drawImage(image, 0, 0, width, height, null);
		g.dispose();
		image = bufferedImage;

		writeJpegFileSupportQuality(destFile, image, quality);
	}

	/**
	 * 保存jpeg文件，支持保存图片质量
	 * 
	 * @throws IOException
	 */
	public static void writeJpegFileSupportQuality(File destFile, BufferedImage image, float quality)
			throws IOException {
		FileOutputStream out = new FileOutputStream(destFile);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
		param.setQuality(quality, false);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(image);
		out.close();
	}

	/**
	 * 重绘Gif
	 * 
	 * @param srcFile
	 * @param destFile
	 * @param width
	 * @param height
	 * @throws Exception
	 */
	public static void redrawGif(File srcFile, File destFile, int width, int height) throws Exception {
		GifDecoder gd = new GifDecoder();
		int status = gd.read(new FileInputStream(srcFile));
		if (status != GifDecoder.STATUS_OK) {
			return;
		}
		AnimatedGifEncoder ge = new AnimatedGifEncoder();
		ge.start(new FileOutputStream(destFile));
		ge.setRepeat(0);
		for (int i = 0; i < gd.getFrameCount(); i++) {
			BufferedImage frame = gd.getFrame(i);
			BufferedImage rescaled = Scalr.resize(frame, Scalr.Mode.FIT_EXACT, width, height);
			int delay = gd.getDelay(i);
			ge.setDelay(delay);
			ge.addFrame(rescaled);
		}
		ge.finish();
	}

	/**
	 * 给图片添加水印、可设置水印图片旋转角度
	 * 
	 * @param iconPath
	 *            水印图片路径
	 * @param srcImgPath
	 *            源图片路径
	 * @param targetPath
	 *            目标图片路径
	 * @param degree
	 *            水印图片旋转角度
	 * @param width
	 *            宽度(与左相比)
	 * @param height
	 *            高度(与顶相比)
	 * @param alpha
	 *            透明度(小于1的数)越接近0越透明
	 */
	public static void markImageByIcon(String iconPath, String srcImgPath, String targetPath, Integer degree,
			Integer width, Integer height, float alpha) {
		OutputStream os = null;
		try {
			BufferedImage sourceImage = ImageUtils.getBufferedImage(new File(srcImgPath));
			BufferedImage targetImage = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null),
					BufferedImage.TYPE_INT_RGB);

			// 得到画笔对象
			Graphics2D g = targetImage.createGraphics();

			// 设置对线段的锯齿状边缘处理
			g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

			g.drawImage(sourceImage.getScaledInstance(sourceImage.getWidth(null), sourceImage.getHeight(null),
					Image.SCALE_SMOOTH), 0, 0, null);

			if (null != degree) {
				// 设置水印旋转
				g.rotate(Math.toRadians(degree), (double) targetImage.getWidth() / 2,
						(double) targetImage.getHeight() / 2);
			}

			// 水印图象的路径 水印一般为gif或者png的，这样可设置透明度
			ImageIcon imgIcon = new ImageIcon(iconPath);

			// 得到Image对象。
			Image img = imgIcon.getImage();

			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

			// 表示水印图片的位置
			g.drawImage(img, width, height, null);

			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));

			g.dispose();

			writeJpegFileSupportQuality(new File(targetPath), targetImage, 1.0f);

			System.out.println("图片完成添加Icon印章。。。。。。");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != os)
					os.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 给图片添加文字水印、可设置水印的旋转角度
	 * 
	 * @param logoText
	 * @param srcImgPath
	 * @param targetPath
	 * @param degree
	 * @param width
	 *            宽度(与左相比)
	 * @param height
	 *            高度(与顶相比)
	 * @param alpha
	 *            透明度(小于1的数)越接近0越透明
	 */
	public static void markByText(String logoText, String srcImgPath, String targetPath, Integer degree, Integer width,
			Integer height, float alpha, String color, int fontSize) {
		// 主图片的路径
		InputStream is = null;
		OutputStream os = null;
		try {
			BufferedImage sourceImage = ImageUtils.getBufferedImage(new File(srcImgPath));
			BufferedImage targetImage = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null),
					BufferedImage.TYPE_INT_RGB);

			// 得到画笔对象
			Graphics2D g = targetImage.createGraphics();

			// 设置对线段的锯齿状边缘处理
			g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

			g.drawImage(sourceImage.getScaledInstance(sourceImage.getWidth(null), sourceImage.getHeight(null),
					Image.SCALE_SMOOTH), 0, 0, null);

			if (null != degree) {
				// 设置水印旋转
				g.rotate(Math.toRadians(degree), (double) targetImage.getWidth() / 2,
						(double) targetImage.getHeight() / 2);
			}

			// 设置颜色
			if (StringUtilsEx.isNullOrEmpty(color)) {
				g.setColor(Color.WHITE);
			} else {
				g.setColor(parseToColor(color.substring(1)));
			}

			// 设置 Font
			g.setFont(new Font("宋体", Font.BOLD, fontSize));

			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));

			// 第一参数->设置的内容，后面两个参数->文字在图片上的坐标位置(x,y) .
			g.drawString(logoText, width, height);

			g.dispose();

			writeJpegFileSupportQuality(new File(targetPath), targetImage, 1.0f);

			System.out.println("图片完成添加文字印章。。。。。。");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != is) {
					is.close();
				}
				if (null != os) {
					os.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 将6位数的颜色代码转换成Color对象
	 * 
	 * @param c
	 *            例如 ff0000 六位的十六进制字符串表示红色
	 * @return java.awt.Color 对象的实例
	 * @exception NumberFormatException
	 */
	public static Color parseToColor(final String c) {
		Color convertedColor = Color.ORANGE;
		try {
			convertedColor = new Color(Integer.parseInt(c, 16));
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		return convertedColor;
	}

	/**
	 * 保存缩略图用于列表显示
	 * 
	 * @param srcFile
	 * @param destFile
	 * @throws Exception
	 */
	public static void saveCyclesSmallFile(String uniqueFileName, File srcFile, File destFile) throws Exception {
		saveCyclesSmallFile(100 * 1024, 10, uniqueFileName, srcFile, destFile);
	}

	/**
	 * 保存缩略图用于列表显示
	 * 
	 * @param srcFile
	 * @param destFile
	 * @throws Exception
	 */
	public static void saveCyclesSmallFile(long smallLimitSize, int cycles, String uniqueFileName, File srcFile,
			File destFile) throws Exception {
		saveCyclesSmallFile(smallLimitSize, cycles, uniqueFileName, srcFile, destFile, 100);
	}

	/**
	 * 保存缩略图
	 * 
	 * @param srcFile
	 * @param destFile
	 * @throws Exception
	 */
	public static void saveCyclesSmallFile(long smallLimitSize, int cycles, String uniqueFileName, File srcFile,
			File destFile, int width) throws Exception {
		if (srcFile.length() > smallLimitSize) {
			File dir = new File(WebUtils.getAbsolutePath(WebUtils.getTempUploadImgUri()));
			if (!dir.exists()) {
				dir.mkdirs();
			}
			File tmpDestFile = new File(WebUtils.getAbsolutePath(WebUtils.getTempUploadImgUri()) + uniqueFileName);
			if (!tmpDestFile.exists()) {
				tmpDestFile.createNewFile();
			}
			ImageUtils.getSmallPicture(srcFile.getPath(), tmpDestFile.getPath(), width, 0, (float) 1, smallLimitSize);
			File newFile = tmpDestFile;
			int i = 0;
			while (newFile.length() > smallLimitSize && i++ < cycles) {
				tmpDestFile = new File(WebUtils.getAbsolutePath(WebUtils.getTempUploadImgUri()) + uniqueFileName);
				if (!tmpDestFile.exists()) {
					tmpDestFile.createNewFile();
				}
				ImageUtils.getSmallPicture(newFile.getPath(), tmpDestFile.getPath(), width, 0, (float) 1.0,
						smallLimitSize);
				newFile = tmpDestFile;
			}
			FileUtils.copyFile(newFile, destFile);
		} else {
			FileUtils.copyFile(srcFile, destFile);
		}
	}

	/**
	 * 此处返回bufferdImage对象，如果jpeg格式，使用jpegreader返回，其他格式使用imageIO返回
	 * 
	 * @param file
	 *            文件对象
	 * @return
	 * @throws Exception
	 */
	public static BufferedImage getBufferedImage(File file) throws Exception {
		String type = getType(file);
		if (TYPE_JPEG.equals(type)) {
			return JpegReader.readImage(file);
		}
		return ImageIO.read(file);
	}
	
	/**
	 * 判断图片是否是正确的尺寸
	 * @param str
	 * @param width
	 * @param heigth
	 * @return
	 */
	public static boolean isImageTheRightSize(String str, int width, int heigth) throws Exception{
		File file = new File(WebUtils.getContextPath() + str);
		FileInputStream fis = new FileInputStream(file);
		BufferedImage bufferedImg = ImageIO.read(fis);
		int imgWidth = bufferedImg.getWidth();
		int imgHeight = bufferedImg.getHeight();
		if(imgWidth == width && imgHeight == heigth){
			return true;
		} else {
			return false;
		}
	}
	
	
	public static void main(String args[]) throws Exception{
	    ImageUtils.getBufferedImage(new File("D:\\即时通\\首页2.jpg"));
	    
	    
	}
}
